从CDC 派生出四个功能更具体的设备描述表类。
l CCientDC
代表窗口客户区的设备描述表。其构造函数CClientDC(CWnd *pWin)通过::GetDC获取指定窗口的客户区的设备描述表HDC,并且使用成员函数Attach把它和CClientDC对象捆绑在一起;其析构函数使用成员函数Detach把设备描述表句柄HDC分离出来,并调用::ReleaseDC释放设备描述表HDC。
2 CPaintDC
仅仅用于响应WM_PAINT消息时绘制窗口,因为它的构造函数调用了::BeginPaint获取设备描述表HDC,并且使用成员函数Attach把它和CPaintDC对象捆绑在一起;析构函数使用成员函数Detach把设备描述表句柄HDC分离出来,并调用::EndPaint释放设备描述表HDC,而::BeginPaint和::EndPaint仅仅在响应WM_PAINT时使用。
3 CMetaFileDC
用于生成元文件。
4 CWindowDC
代表整个窗口区(包括非客户区)的设备描述表。其构造函数CWindowDC(CWnd *pWin)通过::GetWindowDC获取指定窗口的客户区的设备描述表HDC,并使用Attach把它和CWindowDC对象捆绑在一起;其析构函数使用Detach把设备描述表HDC分离出来,调用::ReleaseDC释放设备描述表HDC。
MFC设备描述表类的使用
(1) 使用CPaintDC、CClientDC、CWindowDC的方法
首先,定义一个这些类的实例变量,通常在栈中定义。然后,使用它。
例如,MFC中CView对WM_PAINT消息的实现方法如下:
void CView::OnPaint()
{
// standard paint routine
CPaintDC dc(this);
OnPrepareDC(&dc);
OnDraw(&dc);
}
在栈中定义了CPaintDC类型的变量dc,随着构造函数的调用获取了设备描述表;设备描述表使用完毕,超出其有效范围就被自动地清除,随着析构函数的调用,其获取的设备描述表被释放。
如果希望在堆中创建,例如
CPaintDC *pDC;
pDC = new CPaintDC(this)
则在使用完毕时,用delete删除pDC:
delete pDC;
(2) 直接使用CDC
需要注意的是:在生成CDC对象的时候,并不像它的派生类那样,在构造函数里获取相应的Windows设备描述表。最好不要使用::GetDC等函数来获取一个设备描述表,而是创建一个设备描述表。其构造函数如下:
CDC::CDC()
{
m_hDC = NULL;
m_hAttribDC = NULL;
m_bPrinting = FALSE;
}
其析构函数如下:
CDC::~CDC()
{
if (m_hDC != NULL)
::DeleteDC(Detach());
}
在CDC析构函数中,如果设备描述表句柄不空,则调用DeleteDC删除它。这是直接使用CDC时最好创建Windows设备描述表的理由。如果设备描述表不是创建的,则应该在析构函数被调用前分离出设备描述表句柄并用::RealeaseDC释放它,释放后m_hDC为空,则在析构函数调用时不会执行::DeleteDC。当然,不用担心CDC的派生类的析构函数调用CDC的析构函数,因为CDC::~CDC()不是虚拟析构函数。
直接使用CDC的例子是内存设备上下文,例如:
CDC dcMem; //声明一个CDC对象
dcMem.CreateCompatibleDC(&dc); //创建设备描述表
pbmOld = dcMem.SelectObject(&m_bmBall);//更改设备描述表属性
…//作一些绘制操作
dcMem.SelectObject(pbmOld);//恢复设备描述表的属性
dcMem.DeleteDC(); //可以不调用,而让析构函数去删除设备描述表
本页共50段,1769个字符,3425 Byte(字节)